package yunjiao.javatutorials.guava.concurrent;

import com.google.common.util.concurrent.*;

import java.util.concurrent.Callable;
import java.util.concurrent.Executors;

/**
 * 基本使用示例
 */
public class ListenableFutureTaskExample {

    public static void main(String[] args) {
        // 创建监听执行的线程池
        ListeningExecutorService executor =
                MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(3));

        try {
            // 示例1: 基本用法
            basicUsage(executor);

            // 示例2: 带回调的用法
            callbackUsage(executor);

            // 示例3: 转换结果
            transformUsage(executor);

            combineFutures(executor);

            // 等待异步任务完成
            Thread.sleep(5000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }

    /**
     * 示例1: 基本用法
     */
    private static void basicUsage(ListeningExecutorService executor) {
        System.out.println("=== 基本用法示例 ===");

        // 创建任务
        Callable<String> task = () -> {
            System.out.println("任务开始执行...");
            Thread.sleep(1000); // 模拟耗时操作
            return "任务完成结果";
        };

        // 创建 ListenableFutureTask
        ListenableFutureTask<String> futureTask = ListenableFutureTask.create(task);

        // 提交执行
        executor.execute(futureTask);

        // 添加监听器（非阻塞）
        futureTask.addListener(() -> {
            try {
                String result = futureTask.get();
                System.out.println("监听器收到结果: " + result);
            } catch (Exception e) {
                System.err.println("任务执行失败: " + e.getMessage());
            }
        }, executor);
    }

    /**
     * 示例2: 带回调的用法
     */
    private static void callbackUsage(ListeningExecutorService executor) {
        System.out.println("\n=== 回调用法示例 ===");

        ListenableFuture<String> future = executor.submit(() -> {
            System.out.println("回调任务执行中...");
            Thread.sleep(1500);
            return "回调任务结果";
        });

        // 添加 FutureCallback
        Futures.addCallback(future, new FutureCallback<String>() {
            @Override
            public void onSuccess(String result) {
                System.out.println("回调成功: " + result);
            }

            @Override
            public void onFailure(Throwable t) {
                System.err.println("回调失败: " + t.getMessage());
            }
        }, executor);
    }

    /**
     * 示例3: 转换结果
     */
    private static void transformUsage(ListeningExecutorService executor) {
        System.out.println("\n=== 结果转换示例 ===");

        ListenableFuture<Integer> numberFuture = executor.submit(() -> {
            System.out.println("获取原始数字...");
            Thread.sleep(800);
            return 42;
        });

        // 转换结果
        ListenableFuture<String> transformedFuture =
                Futures.transform(numberFuture, input -> {
                    return "转换后的结果: " + (input * 2);
                }, executor);

        // 处理转换后的结果
        Futures.addCallback(transformedFuture, new FutureCallback<String>() {
            @Override
            public void onSuccess(String result) {
                System.out.println("转换成功: " + result);
            }

            @Override
            public void onFailure(Throwable t) {
                System.err.println("转换失败: " + t.getMessage());
            }
        }, executor);
    }

    /**
     * 示例4: 组合多个 Future
     */
    private static void combineFutures(ListeningExecutorService executor) {
        System.out.println("\n=== 组合Future示例 ===");

        ListenableFuture<String> future1 = executor.submit(() -> {
            Thread.sleep(1000);
            return "Hello";
        });

        ListenableFuture<String> future2 = executor.submit(() -> {
            Thread.sleep(500);
            return "World";
        });

        // 组合两个 Future
        ListenableFuture<String> combined = Futures.transformAsync(
                future1,
                result1 -> Futures.transform(
                        future2,
                        result2 -> result1 + " " + result2 + "!",
                        executor
                ),
                executor
        );

        Futures.addCallback(combined, new FutureCallback<String>() {
            @Override
            public void onSuccess(String result) {
                System.out.println("组合结果: " + result);
            }

            @Override
            public void onFailure(Throwable t) {
                System.err.println("组合失败: " + t.getMessage());
            }
        }, executor);
    }
}
